<?php
/*************************************************************************
    tickets.php
    
    Handles all tickets related actions.
 
    Peter Rotich <peter@osticket.com>
    Copyright (c)  2006-2012 osTicket
    http://www.osticket.com

    Released under the GNU General Public License WITHOUT ANY WARRANTY.
    See LICENSE.TXT for details.

    vim: expandtab sw=4 ts=4 sts=4:
**********************************************************************/

require('staff.inc.php');
require_once(INCLUDE_DIR.'class.ticket.php');
require_once(INCLUDE_DIR.'class.dept.php');
require_once(INCLUDE_DIR.'class.filter.php');
require_once(INCLUDE_DIR.'class.canned.php');


$page='';
$ticket=null; //clean start.
//LOCKDOWN...See if the id provided is actually valid and if the user has access.
if($_REQUEST['id']) {
    if(!($ticket=Ticket::lookup($_REQUEST['id'])))
         $errors['err']=_('Unknown or invalid ticket ID');
    elseif(!$ticket->checkStaffAccess($thisstaff)) {
        $errors['err']=_('Access denied. Contact admin if you believe this is in error');
        $ticket=null; //Clear ticket obj.
    }
}
//At this stage we know the access status. we can process the post.
if($_POST && !$errors):

    if($ticket && $ticket->getId()) {
        //More coffee please.
        $errors=array();
        $lock=$ticket->getLock(); //Ticket lock if any
        $statusKeys=array('open'=>'Open','Reopen'=>'Open','Close'=>'Closed');
        switch(strtolower($_POST['a'])):
        case 'reply':
            if(!$thisstaff->canPostReply())
                $errors['err'] = _('Action denied. Contact admin for access');
            else {

                if(!$_POST['msgId'])
                    $errors['err']=_('Missing message ID - Internal error');
                if(!$_POST['response'])
                    $errors['response']=_('Response required');
            
                //Use locks to avoid double replies
                if($lock && $lock->getStaffId()!=$thisstaff->getId())
                    $errors['err']=_('Action Denied. Ticket is locked by someone else!');
            
                //Make sure the email is not banned
                if(!$errors['err'] && TicketFilter::isBanned($ticket->getEmail()))
                    $errors['err']=_('Email is in banlist. Must be removed to reply.');
            }

            $wasOpen =($ticket->isOpen());
            //If no error...do the do.
            if(!$errors && ($respId=$ticket->postReply($_POST, $errorsi, isset($_POST['emailreply'])))) {
                $msg=_('Reply posted successfully');
                $ticket->reload();
                if($ticket->isClosed() && $wasOpen)
                    $ticket=null;

            } elseif(!$errors['err']) {
                $errors['err']=_('Unable to post the reply. Correct the errors below and try again!');
            }
            break;
        case 'transfer': /** Transfer ticket **/
            //Check permission 
            if(!$thisstaff->canTransferTickets())
                $errors['err']=$errors['transfer'] = 'Action Denied. You are not allowed to transfer tickets.';
            else {

                //Check target dept.
                if(!$_POST['deptId'])
                    $errors['deptId'] = _('Select department');
                elseif($_POST['deptId']==$ticket->getDeptId())
                    $errors['deptId'] = _('Ticket already in the department');
                elseif(!($dept=Dept::lookup($_POST['deptId'])))
                    $errors['deptId'] = _('Unknown or invalid department');
            
                //Transfer message - required.
                if(!$_POST['transfer_comments'])
                    $errors['transfer_comments'] = _('Transfer comments required');
                elseif(strlen($_POST['transfer_comments'])<5)
                    $errors['transfer_comments'] = _('Transfer comments too short!');
           
                //If no errors - them attempt the transfer.
                if(!$errors && $ticket->transfer($_POST['deptId'], $_POST['transfer_comments'])) {
                    $msg = _('Ticket transferred successfully to').' '.$ticket->getDeptName();
                    //Check to make sure the staff still has access to the ticket
                    if(!$ticket->checkStaffAccess($thisstaff))
                        $ticket=null;

                } elseif(!$errors['transfer']) {
                    $errors['err'] = _('Unable to complete the ticket transfer');
                    $errors['transfer']=_('Correct the error(s) below and try again!');
                }
            }
            break;
        case 'assign':

             if(!$thisstaff->canAssignTickets())
                 $errors['err']=$errors['assign'] = _('Action Denied. You are not allowed to assign/reassign tickets.');
             else {

                 $id = preg_replace("/[^0-9]/", "",$_POST['assignId']);
                 $claim = (is_numeric($_POST['assignId']) && $_POST['assignId']==$thisstaff->getId()); 

                 if(!$_POST['assignId'] || !$id)
                     $errors['assignId'] = _('Select assignee');
                 elseif($_POST['assignId'][0]!='s' && $_POST['assignId'][0]!='t' && !$claim)
                     $errors['assignId']=_('Invalid assignee ID - get technical support');
                 elseif($ticket->isAssigned()) {
                     if($_POST['assignId'][0]=='s' && $id==$ticket->getStaffId())
                         $errors['assignId']=_('Ticket already assigned to the staff.');
                     elseif($_POST['assignId'][0]=='t' && $id==$ticket->getTeamId())
                         $errors['assignId']=_('Ticket already assigned to the team.');
                 }

                 //Comments are not required on self-assignment (claim)
                 if($claim && !$_POST['assign_comments'])
                     $_POST['assign_comments'] = _('Ticket claimed by').' '.$thisstaff->getName();
                 elseif(!$_POST['assign_comments'])
                     $errors['assign_comments'] = _('Assignment comments required');
                 elseif(strlen($_POST['assign_comments'])<5)
                         $errors['assign_comments'] = _('Comment too short');
                 
                 if(!$errors && $ticket->assign($_POST['assignId'], $_POST['assign_comments'], !$claim)) {
                     if($claim) {
                         $msg = _('Ticket is NOW assigned to you!');
                     } else {
                         $msg=_('Ticket assigned successfully to').' '.$ticket->getAssigned();
                         TicketLock::removeStaffLocks($thisstaff->getId(), $ticket->getId());
                         $ticket=null;
                     }
                 } elseif(!$errors['assign']) {
                     $errors['err'] = _('Unable to complete the ticket assignment');
                     $errors['assign'] = _('Correct the error(s) below and try again!');
                 }
             }
            break; 
        case 'postnote': /* Post Internal Note */
            //Make sure the staff can set desired state
            if($_POST['state']) {
                if($_POST['state']=='closed' && !$thisstaff->canCloseTickets())
                    $errors['state'] = _("You don't have permission to close tickets");
                elseif(in_array($_POST['state'], array('overdue', 'notdue', 'unassigned'))
                        && (!($dept=$ticket->getDept()) || !$dept->isManager($thisstaff)))
                    $errors['state'] = _("You don't have permission to set the state");
            }

            $wasOpen = ($ticket->isOpen());
            if(($noteId=$ticket->postNote($_POST, $errors, $thisstaff))) {
                $msg=_('Internal note posted successfully');
                if($wasOpen && $ticket->isClosed())
                    $ticket = null; //Going back to main listing.
            } else {
                $errors['err'] = _('Unable to post internal note - missing or invalid data.');
                $errors['postnote'] = _('Unable to post the note. Correct the error(s) below and try again!');
            }
            break;
        case 'edit':
        case 'update':
            if(!$ticket || !$thisstaff->canEditTickets())
                $errors['err']=_('Perm. Denied. You are not allowed to edit tickets');
            elseif($ticket->update($_POST,$errors)) {
                $msg=_('Ticket updated successfully');
                $_REQUEST['a'] = null; //Clear edit action - going back to view.
                //Check to make sure the staff STILL has access post-update (e.g dept change).
                if(!$ticket->checkStaffAccess($thisstaff))
                    $ticket=null;
            } elseif(!$errors['err']) {
                $errors['err']=_('Unable to update the ticket. Correct the errors below and try again!');
            }
            break;
        case 'process':
            switch(strtolower($_POST['do'])):
                case 'close':
                    if(!$thisstaff->canCloseTickets()) {
                        $errors['err'] = _('Perm. Denied. You are not allowed to close tickets.');
                    } elseif($ticket->isClosed()) {
                        $errors['err'] = _('Ticket is already closed!');
                    } elseif($ticket->close()) {
                        $msg=_('Ticket #').$ticket->getExtId().' '._('status set to CLOSED');
                        //Log internal note
                        if($_POST['ticket_status_notes'])
                            $note = $_POST['ticket_status_notes'];
                        else
                            $note=_('Ticket closed (without comments)');
                        
                        $ticket->logNote(_('Ticket Closed'), $note, $thisstaff);
                        
                        //Going back to main listing.
                        TicketLock::removeStaffLocks($thisstaff->getId(), $ticket->getId());
                        $page=$ticket=null;

                    } else {
                        $errors['err']=_('Problems closing the ticket. Try again');
                    }
                    break;
                case 'reopen':
                    //if staff can close or create tickets ...then assume they can reopen.
                    if(!$thisstaff->canCloseTickets() && !$thisstaff->canCreateTickets()) {
                        $errors['err']=_('Perm. Denied. You are not allowed to reopen tickets.');
                    } elseif($ticket->isOpen()) {
                        $errors['err'] = _('Ticket is already open!');
                    } elseif($ticket->reopen()) {
                        $msg=_('Ticket REOPENED');

                        if($_POST['ticket_status_notes'])
                            $note = $_POST['ticket_status_notes'];
                        else
                            $note=_('Ticket reopened (without comments)');

                        $ticket->logNote(_('Ticket Reopened'), $note, $thisstaff);

                    } else {
                        $errors['err']=_('Problems reopening the ticket. Try again');
                    }
                    break;
                case 'release':
                    if(!$ticket->isAssigned() || !($assigned=$ticket->getAssigned())) {
                        $errors['err'] = _('Ticket is not assigned!');
                    } elseif($ticket->release()) {
                        $msg=_('Ticket released (unassigned) from').' '.$assigned;
                        $ticket->logActivity(_('Ticket unassigned'),$msg.' '._('by').' '.$thisstaff->getName());
                    } else {
                        $errors['err'] = _('Problems releasing the ticket. Try again');
                    }
                    break;
                case 'claim':
                    if(!$thisstaff->canAssignTickets()) {
                        $errors['err'] = _('Perm. Denied. You are not allowed to assign/claim tickets.');
                    } elseif(!$ticket->isOpen()) {
                        $errors['err'] = _('Only open tickets can be assigned');
                    } elseif($ticket->isAssigned()) {
                        $errors['err'] = _('Ticket is already assigned to').' '.$ticket->getAssigned();
                    } elseif($ticket->assignToStaff($thisstaff->getId(), (_('Ticket claimed by').' '.$thisstaff->getName()), false)) {
                        $msg = _('Ticket is now assigned to you!');
                    } else {
                        $errors['err'] = _('Problems assigning the ticket. Try again');
                    }
                    break;
                case 'overdue':
                    $dept = $ticket->getDept();
                    if(!$dept || !$dept->isManager($thisstaff)) {
                        $errors['err']=_('Perm. Denied. You are not allowed to flag tickets overdue');
                    } elseif($ticket->markOverdue()) {
                        $msg=_('Ticket flagged as overdue');
                        $ticket->logActivity(_('Ticket Marked Overdue'),($msg.' '._('by').' '.$thisstaff->getName()));
                    } else {
                        $errors['err']=_('Problems marking the the ticket overdue. Try again');
                    }
                    break;
                case 'answered':
                    $dept = $ticket->getDept();
                    if(!$dept || !$dept->isManager($thisstaff)) {
                        $errors['err']=_('Perm. Denied. You are not allowed to flag tickets');
                    } elseif($ticket->markAnswered()) {
                        $msg=_('Ticket flagged as answered');
                        $ticket->logActivity(_('Ticket Marked Answered'),($msg.' '._('by').' '.$thisstaff->getName()));
                    } else {
                        $errors['err']=_('Problems marking the the ticket answered. Try again');
                    }
                    break;
                case 'unanswered':
                    $dept = $ticket->getDept();
                    if(!$dept || !$dept->isManager($thisstaff)) {
                        $errors['err']=_('Perm. Denied. You are not allowed to flag tickets');
                    } elseif($ticket->markUnAnswered()) {
                        $msg=_('Ticket flagged as unanswered');
                        $ticket->logActivity(_('Ticket Marked Unanswered'),($msg.' '._('by').' '.$thisstaff->getName()));
                    } else {
                        $errors['err']=_('Problems marking the the ticket unanswered. Try again');
                    }
                    break;
                case 'banemail':
                    if(!$thisstaff->canBanEmails()) {
                        $errors['err']=_('Perm. Denied. You are not allowed to ban emails');
                    } elseif(BanList::includes($ticket->getEmail())) {
                        $errors['err']=_('Email already in banlist');
                    } elseif(Banlist::add($ticket->getEmail(),$thisstaff->getName())) {
                        $msg=_('Email').' ('.$ticket->getEmail().') '._('added to banlist');
                    } else {
                        $errors['err']=_('Unable to add the email to banlist');
                    }
                    break;
                case 'unbanemail':
                    if(!$thisstaff->canBanEmails()) {
                        $errors['err'] = _('Perm. Denied. You are not allowed to remove emails from banlist.');
                    } elseif(Banlist::remove($ticket->getEmail())) {
                        $msg = _('Email removed from banlist');
                    } elseif(!BanList::includes($ticket->getEmail())) {
                        $warn = _('Email is not in the banlist'); 
                    } else {
                        $errors['err']=_('Unable to remove the email from banlist. Try again.');
                    }
                    break;
                case 'delete': // Dude what are you trying to hide? bad customer support??
                    if(!$thisstaff->canDeleteTickets()) {
                        $errors['err']=_('Perm. Denied. You are not allowed to DELETE tickets!!');
                    } elseif($ticket->delete()) {
                        $msg=_('Ticket #').$ticket->getNumber().' '._('deleted successfully');
                        //Log a debug note
                        $ost->logDebug(_('Ticket #').$ticket->getNumber().' '._('deleted'),
                                sprintf(_('Ticket #%s deleted by %s'),
                                    $ticket->getNumber(), $thisstaff->getName())
                                );
                        $ticket=null; //clear the object.
                    } else {
                        $errors['err']=_('Problems deleting the ticket. Try again');
                    }
                    break;
                default:
                    $errors['err']=_('You must select action to perform');
            endswitch;
            break;
        default:
            $errors['err']=_('Unknown action');
        endswitch;
        if($ticket && is_object($ticket))
            $ticket->reload();//Reload ticket info following post processing
    }elseif($_POST['a']) {

        switch($_POST['a']) {
            case 'mass_process':
                if(!$thisstaff->canManageTickets())
                    $errors['err']=_('You do not have permission to mass manage tickets. Contact admin for such access');    
                elseif(!$_POST['tids'] || !is_array($_POST['tids']))
                    $errors['err']=_('No tickets selected. You must select at least one ticket.');
                else {
                    $count=count($_POST['tids']);
                    $i = 0;
                    switch(strtolower($_POST['do'])) {
                        case 'reopen':
                            if($thisstaff->canCloseTickets() || $thisstaff->canCreateTickets()) {
                                $note=_('Ticket reopened by').' '.$thisstaff->getName();
                                foreach($_POST['tids'] as $k=>$v) {
                                    if(($t=Ticket::lookup($v)) && $t->isClosed() && @$t->reopen()) {
                                        $i++;
                                        $t->logNote(_('Ticket Reopened'), $note, $thisstaff);
                                    }
                                }

                                if($i==$count)
                                    $msg = _('Selected tickets')." ($i) "._('reopened successfully');
                                elseif($i)
                                    $warn = "$i "._("of")." $count "._("selected tickets reopened");
                                else
                                    $errors['err'] = _('Unable to reopen selected tickets');
                            } else {
                                $errors['err'] = _('You do not have permission to reopen tickets');
                            }
                            break;
                        case 'close':
                            if($thisstaff->canCloseTickets()) {
                                $note=_('Ticket closed without response by').' '.$thisstaff->getName();
                                foreach($_POST['tids'] as $k=>$v) {
                                    if(($t=Ticket::lookup($v)) && $t->isOpen() && @$t->close()) { 
                                        $i++;
                                        $t->logNote(_('Ticket Closed'), $note, $thisstaff);
                                    }
                                }

                                if($i==$count)
                                    $msg =_('Selected tickets')." ($i) "._('closed succesfully');
                                elseif($i)
                                    $warn = "$i "._("of")." $count "._("selected tickets closed");
                                else
                                    $errors['err'] = _('Unable to close selected tickets');
                            } else {
                                $errors['err'] = _('You do not have permission to close tickets');
                            }
                            break;
                        case 'mark_overdue':
                            $note=_('Ticket flagged as overdue by').' '.$thisstaff->getName();
                            foreach($_POST['tids'] as $k=>$v) {
                                if(($t=Ticket::lookup($v)) && !$t->isOverdue() && $t->markOverdue()) {
                                    $i++;
                                    $t->logNote(_('Ticket Marked Overdue'), $note, $thisstaff);
                                }
                            }

                            if($i==$count)
                                $msg = _('Selected tickets')." ($i) "._('marked overdue');
                            elseif($i)
                                $warn = "$i "._("of")." $count "._("selected tickets marked overdue");
                            else
                                $errors['err'] = _('Unable to flag selected tickets as overdue');
                            break;
                        case 'delete':
                            if($thisstaff->canDeleteTickets()) {
                                foreach($_POST['tids'] as $k=>$v) {
                                    if(($t=Ticket::lookup($v)) && @$t->delete()) $i++;
                                }
                        
                                //Log a warning
                                if($i) {
                                    $log = sprintf('%s (%s) '._('just deleted %d ticket(s)'),
                                            $thisstaff->getName(), $thisstaff->getUserName(), $i);
                                    $ost->logWarning(_('Tickets deleted'), $log, false);

                                }

                                if($i==$count)
                                    $msg = _('Selected tickets')." ($i) "._('deleted successfully');
                                elseif($i)
                                    $warn = "$i "._("of")." $count "._("selected tickets deleted");
                                else
                                    $errors['err'] = _('Unable to delete selected tickets');
                            } else {
                                $errors['err'] = _('You do not have permission to delete tickets');
                            }
                            break;
                        default:
                            $errors['err']=_('Unknown or unsupported action - get technical help');
                    }
                }
                break;
            case 'open':
                $ticket=null;
                if(!$thisstaff || !$thisstaff->canCreateTickets()) {
                     $errors['err']=_('You do not have permission to create tickets. Contact admin for such access');
                }elseif(($ticket=Ticket::open($_POST, $errors))) {
                    $msg=_('Ticket created successfully');
                    $_REQUEST['a']=null;
                    if(!$ticket->checkStaffAccess($thisstaff) || $ticket->isClosed())
                        $ticket=null;
                }elseif(!$errors['err']) {
                    $errors['err']=_('Unable to create the ticket. Correct the error(s) and try again');
                }
                break;
        }
    }
    if(!$errors)
        $thisstaff ->resetStats(); //We'll need to reflect any changes just made!
endif;

/*... Quick stats ...*/
$stats= $thisstaff->getTicketsStats();

//Navigation
$nav->setTabActive('tickets');
if($cfg->showAnsweredTickets()) {
    $nav->addSubMenu(array('desc'=>_('Open').' ('.($stats['open']+$stats['answered']).')',
                            'title'=>_('Open Tickets'),
                            'href'=>'tickets.php',
                            'iconclass'=>'Ticket'),
                        (!$_REQUEST['status'] || $_REQUEST['status']=='open'));
} else {

    if($stats) {
        $nav->addSubMenu(array('desc'=>_('Open').' ('.$stats['open'].')',
                               'title'=>_('Open Tickets'),
                               'href'=>'tickets.php',
                               'iconclass'=>'Ticket'),
                            (!$_REQUEST['status'] || $_REQUEST['status']=='open'));
    }

    if($stats['answered']) {
        $nav->addSubMenu(array('desc'=>_('Answered').' ('.$stats['answered'].')',
                               'title'=>_('Answered Tickets'),
                               'href'=>'tickets.php?status=answered',
                               'iconclass'=>'answeredTickets'),
                            ($_REQUEST['status']=='answered')); 
    }
}

if($stats['assigned']) {
    if(!$ost->getWarning() && $stats['assigned']>10)
        $ost->setWarning($stats['assigned'].' '._('tickets assigned to you! Do something about it!'));

    $nav->addSubMenu(array('desc'=>_('My Tickets').' ('.$stats['assigned'].')',
                           'title'=>_('Assigned Tickets'),
                           'href'=>'tickets.php?status=assigned',
                           'iconclass'=>'assignedTickets'),
                        ($_REQUEST['status']=='assigned'));
}

if($stats['overdue']) {
    $nav->addSubMenu(array('desc'=>_('Overdue').' ('.$stats['overdue'].')',
                           'title'=>_('Stale Tickets'),
                           'href'=>'tickets.php?status=overdue',
                           'iconclass'=>'overdueTickets'),
                        ($_REQUEST['status']=='overdue'));

    if(!$sysnotice && $stats['overdue']>10)
        $sysnotice=$stats['overdue']._(' overdue tickets!');
}

if($thisstaff->showAssignedOnly() && $stats['closed']) {
    $nav->addSubMenu(array('desc'=>_('My Closed Tickets').' ('.$stats['closed'].')',
                           'title'=>_('My Closed Tickets'),
                           'href'=>'tickets.php?status=closed',
                           'iconclass'=>'closedTickets'),
                        ($_REQUEST['status']=='closed'));
} else {

    $nav->addSubMenu(array('desc'=>_('Closed Tickets'),
                           'title'=>_('Closed Tickets'),
                           'href'=>'tickets.php?status=closed',
                           'iconclass'=>'closedTickets'),
                        ($_REQUEST['status']=='closed'));
}

if($thisstaff->canCreateTickets()) {
    $nav->addSubMenu(array('desc'=>_('New Ticket'),
                           'href'=>'tickets.php?a=open',
                           'iconclass'=>'newTicket'),
                        ($_REQUEST['a']=='open'));    
}


$inc = 'tickets.inc.php';
if($ticket) {
    $ost->setPageTitle('Ticket #'.$ticket->getNumber());
    $nav->setActiveSubMenu(-1);
    $inc = 'ticket-view.inc.php';
    if($_REQUEST['a']=='edit' && $thisstaff->canEditTickets()) 
        $inc = 'ticket-edit.inc.php';
    elseif($_REQUEST['a'] == 'print' && !$ticket->pdfExport($_REQUEST['psize'], $_REQUEST['notes']))
        $errors['err'] = _('Internal error: Unable to export the ticket to PDF for print.');
} else {
    $inc = 'tickets.inc.php';
    if($_REQUEST['a']=='open' && $thisstaff->canCreateTickets())
        $inc = 'ticket-open.inc.php';
    elseif($_REQUEST['a'] == 'export') {
        require_once(INCLUDE_DIR.'class.export.php');
        $ts = strftime('%Y%m%d');
        if (!($token=$_REQUEST['h']))
            $errors['err'] = _('Query token required');
        elseif (!($query=$_SESSION['search_'.$token]))
            $errors['err'] = _('Query token not found');
        elseif (!Export::saveTickets($query, "tickets-$ts.csv", 'csv'))
            $errors['err'] = _('Internal error: Unable to dump query results');
    }

    //Clear active submenu on search with no status
    if($_REQUEST['a']=='search' && !$_REQUEST['status'])
        $nav->setActiveSubMenu(-1);

    //set refresh rate if the user has it configured
    if(!$_POST && !$_REQUEST['a'] && ($min=$thisstaff->getRefreshRate()))
        $ost->addExtraHeader('<meta http-equiv="refresh" content="'.($min*60).'" />');
}

require_once(STAFFINC_DIR.'header.inc.php');
require_once(STAFFINC_DIR.$inc);
require_once(STAFFINC_DIR.'footer.inc.php');
?>
